import { Logger } from '@nestjs/common';

type ExceptionType = {
  error: string;
  statusCode: number;
  message?: string;
};

export const ExceptionMap = {
  Bad_Request: {
    error: 'Bad Request',
    statusCode: 400,
  },
  Unauthorized: {
    error: 'Unauthorized',
    statusCode: 401,
  },
  Payment_Required: {
    error: 'Payment Required',
    statusCode: 402,
  },
  Forbidden: {
    error: 'Forbidden',
    statusCode: 403,
  },
  Not_Found: {
    error: 'Not Found',
    statusCode: 404,
  },
  Method_Not_Allowed: {
    error: 'Method Not Allowed',
    statusCode: 405,
  },
  Not_Acceptable: {
    error: 'Not Acceptable',
    statusCode: 406,
  },
  Proxy_Authentication_Required: {
    error: 'Proxy Authentication Required',
    statusCode: 407,
  },
  Request_Timeout: {
    error: 'Request Timeout',
    statusCode: 408,
  },
  Conflict: {
    error: 'Conflict',
    statusCode: 409,
  },
  Internal_Server_Error: {
    error: 'Internal Server Error',
    statusCode: 500,
  },
};

/*
 * @param response http response
 * @param statusCode 响应码 404,409....
 * @param errorName 返回给客户端错误码  Not Found,Confict ....
 * @param message 返回给客户端的message字段错误信息
 * @param detail 返回给客户端的错误详细信息 默认为空
 * @param exception 原始的错误对象 Error类型或其派生类
 */
export function sendExceptionResponse({
  response,
  statusCode,
  errorName,
  message,
  detail = null,
  exception,
}) {
  const resJson = {
    error: errorName,
    message: message,
    detail: detail,
  };
  response.status(statusCode).json(resJson);
  const req = response.req;
  //日志信息
  const logFormat = ` 
    Request original url: ${req.originalUrl}
    Method: ${req.method}
    IP: ${req.ip}
    Parmas: ${JSON.stringify(req.params)}
    Headers${JSON.stringify(req.headers)}
    Body: ${JSON.stringify(req.body)}
    Message:${JSON.stringify(message)}
    Detail: ${JSON.stringify(detail)}
  `;
  //日志打印request信息、堆栈异常信息、异常类名
  const stack = exception.stack || '';
  Logger.error(logFormat, stack, exception.name);
}

/**
 * @description 通过statusCode获取异常对象
 * @param statusCodeInput
 * @returns
 */
export const getExceptionByStatusCode = (
  statusCodeInput: number,
): ExceptionType => {
  let exception;
  for (const prop in ExceptionMap) {
    const val = ExceptionMap[prop];
    const { statusCode } = val;
    if (statusCode === statusCodeInput) {
      exception = val;
      break;
    }
  }
  //如果没匹配到，使用Bad_Request
  if (!exception) {
    exception = ExceptionMap.Bad_Request;
  }
  return exception;
};
